package main.java;
import java.util.Iterator;
import java.util.Vector;


public class JuegoImplParaTest implements Juego {
	private boolean fin_partida;
	private Integer num_ref;
	private Integer id_jugador_turno; // @jjpl 30/1/2012 -> "visibility modified"
	private Jugador jugador2;
	private Jugador jugador1;
	private Mazo_productos mazo_prod;
	private Mazo_pedidos mazo_pedidos;
	private Vector<Bocadillo> bocadillos;
	private Interfaz in=new InterfazImpl();
	
	
	public JuegoImplParaTest(){
		fin_partida=false;
		id_jugador_turno=1;
		this.bocadillos = new Vector<Bocadillo>();
		this.setMazo_prod(new Mazo_productosImpl());
	    this.setMazo_pedidos(new Mazo_pedidosImpl());
	}
	
	
	public Integer getNumRef(){
		return num_ref;
	}

	
	public void cambiar_turno() {
		id_jugador_turno = (id_jugador_turno == 1 ? 2 :1);
		in.cambio_de_turno(id_jugador_turno);
		
	}

	
	public void iniciar_partida() {
		mazo_pedidos.preparar();
	    mazo_prod.preparar();
		Vector<C_producto> mano1=mazo_prod.coger_panes();
		Vector<C_producto> mano2=mazo_prod.coger_panes();
		jugador1=new JugadorImpl("Jugador1",1,mano1);
		jugador2=new JugadorImpl("Jugador2",2,mano2);
		in.mostrar_inicio();
		while(!fin_partida){
			turno();
			in.cambio_de_turno(id_jugador_turno);
		}
		in.mostrar_final(getJugador(1).get_puntos(), getJugador(2).get_puntos());
	}
	
	private void turno(){
        C_producto prod_ref=getMazo_prod().sacar_prod();
        setNumRef(prod_ref.get_num_ref());
        in.mostrar_carta_referencia(prod_ref);
        if(prod_ref.get_num_ref()==0){
        	if(this.bocadillos.size()==0){
        		in.error(4);
        		mazo_prod.descartar(prod_ref); 
        		turno();
        	}
        	else if(!poder_colocar_orejas()){
        		in.error(5);
        		mazo_prod.descartar(prod_ref);   
        		turno();
        	}
        	else {
        		int pedido_orejas=in.decidir_orejas();
        		while(this.bocadillos.get(pedido_orejas).necesita_orejas()){
        			in.error(6);
        			pedido_orejas=in.decidir_orejas();
        		}
        		this.bocadillos.get(pedido_orejas).colocar_orejas(prod_ref);          
        		turno();              
        	}
        }
        else{
        	if(getNumRef()>=this.bocadillos.size())
                   sacar_bocadillo(getMazo_pedidos().sacar_pedido());
            if(getMazo_pedidos().getNumDescartes()>=4 || getMazo_pedidos().get_pedidos().size()==0)
            	terminar_partida();
            if (!fin_partida){
            	accion();
            	if (in.decidir_entregar())
            		entregar_pedido();
            	cambiar_turno();
            	accion();
            	if (in.decidir_entregar())
            		entregar_pedido();
            }
        }
    }
	
	public void setNumRef(Integer nr) {
		this.num_ref =nr;

	}

	private void terminar_partida() {
		this.fin_partida=true;
		if (getMazo_pedidos().getNumDescartes()>=4){
			jugador1.add_puntos(-(jugador1.get_mano().size()));
			jugador2.add_puntos(-(jugador2.get_mano().size()));
		}

	}

	public Mazo_pedidos getMazo_pedidos() {
		return mazo_pedidos;
	}


	public void setMazo_pedidos(Mazo_pedidos mazo_pedidos) {
		this.mazo_pedidos = mazo_pedidos;
	}
	
	

	public Mazo_productos getMazo_prod() {
		return mazo_prod;
	}


	public void setMazo_prod(Mazo_productos mazo_prod) {
		this.mazo_prod = mazo_prod;
	}

	private Jugador getJugador(int numJugador) {
		if(numJugador!=1 && numJugador!=2)
			throw new IllegalArgumentException("Numero de jugador incorrecto");
		Jugador jug;
		if(numJugador==1)
			jug=jugador1;
		else
			jug=jugador2;
		return jug;
	}


	
	//antes de llamar a descartar carta hay que comprobar que la mano no esté vacía
	private void descartar_carta(){
		int i,elegida, nr=this.getNumRef();
		C_producto carta;
		for (i=1;i<=nr;i++){
			if (this.id_jugador_turno ==1){
				elegida= in.elegir_descartar(jugador1.get_mano());
				carta=jugador1.descartar(elegida);
				if (this.jugador1.get_mano().size() ==0)
					i=nr+1;
			}
			else{
				elegida= in.elegir_descartar(jugador2.get_mano());
				carta=jugador2.descartar(elegida);
				if (this.jugador2.get_mano().size() ==0)
					i=nr+1;
			}
			mazo_prod.descartar(carta);
			if (nr<=i || !in.seguir())		
				i=nr+1;
		}
			
		
	}
	
	//antes de llamar a coger_carta hay que comprobar que la mano no esté llena 
	private void coger_carta(){
		int i, nr=this.getNumRef();
		C_producto carta;
		for (i=1;i<=nr;i++){
			carta=mazo_prod.sacar_prod();
			if (this.id_jugador_turno ==1){
				this.jugador1.add_producto(carta);
				in.mostrar_coger_carta(carta);
				if (this.jugador1.get_mano().size() == 10)
					i=nr+1;
			}
			else{
				this.jugador2.add_producto(carta);
				in.mostrar_coger_carta(carta);
				if (this.jugador2.get_mano().size() == 10)
					i=nr+1;
			}
			mazo_prod.descartar(carta);
			if (nr<=i || !in.seguir())			
				i=nr+1;
		}
		
		
		
	}
	//antes de llamar a buscar_carta hay que comprobar que la mano no esté llena 
	private void buscar_carta(){
		Vector<C_producto> cartas;
		int i,nr,elegido;
		Iterator<C_producto> it;
		cartas = new Vector<C_producto>();
		nr=2*this.getNumRef();
		for (i=1;i<=nr;i++){
			cartas.add( mazo_prod.sacar_prod());			
		}
		elegido=in.elegir_buscar(cartas);
		if (this.id_jugador_turno ==1)
			this.jugador1.add_producto(cartas.remove(elegido));
		else	
			this.jugador2.add_producto(cartas.remove(elegido));
		it=cartas.iterator();
		while (it.hasNext()){
			mazo_prod.descartar(it.next());
			it.remove();}
		}
	
	private void preparar_bocadillo(int nr){
		try{
			Jugador jug=(id_jugador_turno==1?jugador1:jugador2);
			int carta,bocadillo;
			carta=in.elegir_carta(jug.get_mano());
			bocadillo=in.elegir_bocadillo(bocadillos);
			bocadillos.get(bocadillo).add_producto(jug.get_mano().get(carta), id_jugador_turno);
			jug.descartar(carta);
			if (nr>1 && jug.get_mano().size()>0 && in.seguir()){
				preparar_bocadillo(nr-1);
			}
		}
		catch (CartaIncorrectaException e){
			in.error(2);
			if (in.seguir()){
				preparar_bocadillo(nr);
			}
		}
	}
	
	//es la accion del jugador despues de haberse sacado la carta de producto para el
	//numero de referencia
	private void accion(){
		int acc=in.decidir_accion();
        switch (acc){
            case 1: if ((id_jugador_turno==1?jugador1:jugador2).get_mano().size() > 9){                                    //Para que pueda ejecutar otra accion sino puede coger ni una carta
                        in.error(0);
                        accion();
                    }
                    else{
                       	coger_carta();
                    }
                    break;
            case 2:    if ((id_jugador_turno==1?jugador1:jugador2).get_mano().size() < 1){
                        in.error(1);
                        accion();
                    }
                    else{
                    	descartar_carta();
                    }
                    break;
            case 3:    if ((id_jugador_turno==1?jugador1:jugador2).get_mano().size() > 9){
                        in.error(0);
                        accion();
                    }
                    else
                        buscar_carta();
                    break;
            case 4:    if ((id_jugador_turno==1?jugador1:jugador2).get_mano().size() < 1){                                                  
                        in.error(1);                 
                        accion();
                    }
                    else{
                        preparar_bocadillo(num_ref);
                    }
                    break;
            case 5:    in.mostrar_mano((id_jugador_turno==1?jugador1:jugador2).get_mano());
                    accion();
                    break;
            case 6:in.mostrar_bocadillos(this.bocadillos);
                    accion();
                    break;           
            }
        
	} 
		
	
	
	//Saca un nuevo pedido si o si, antes de llamarlo hay que comprobar si es necesario
	//y sacar el pedido del mazo de pedidos
	public void sacar_bocadillo(C_pedido pedido){
		in.mostrar_sacar_bocadillo(pedido);
		if (bocadillos.size()==4){
			mazo_prod.descartar(bocadillos.get(0).descartar());
			mazo_pedidos.descartar();
			bocadillos.remove(0);
		}
		bocadillos.add(new BocadilloImpl(pedido));
		
	}
	
	//Antes de llamar a entregar_pedido hay que comprobar que haya al menos un bocadillo en mesa
	//pregunta que pedido se quiere entregar
	//y en el caso de que se pueda entregar,
	//actualiza los puntos del jugador correspondiente
	//y quita el pedido de la mesa
	private void entregar_pedido(){
		int elegido,faltan,puntos;
		Boolean correcto=true;
		C_producto prod;
		elegido=in.elegir_bocadillo(bocadillos);
		if (bocadillos.get(elegido).tiene_comodin(id_jugador_turno))
			faltan=bocadillos.get(elegido).entregar(id_jugador_turno,in.elegir_comodin());
		else
			faltan=bocadillos.get(elegido).entregar(id_jugador_turno);
		if (faltan==-1){			//No se puede entregar el bocadillo
			in.error(3);	//por falta de algun pan negro
			}					//u orejas si son necesarias
		else{
			if (faltan>0){						//En el caso de que falte algun producto
				prod=mazo_prod.sacar_prod();	//se intenta engañar al cliente
				if (prod.get_num_ref()<=faltan)
					correcto=false;
				mazo_prod.descartar(prod);
			}
			puntos=bocadillos.get(elegido).get_pedido().get_precio();
			if (bocadillos.get(elegido).necesita_orejas())
				puntos++;
			((id_jugador_turno==1^correcto)?jugador2:jugador1).add_puntos(puntos);
				in.entregar_bocadillo(correcto);
			mazo_prod.descartar(bocadillos.get(elegido).descartar());
			bocadillos.remove(elegido);
			}
		if (bocadillos.size()>0 && in.seguir()){
			entregar_pedido();
			}
		
	}
	
	//comprueba si se pueden colocar las orejas en algún bocadillo		
	public Boolean poder_colocar_orejas(){
		Boolean puede=false;
		Iterator<Bocadillo> it=bocadillos.iterator();
		while(!puede && it.hasNext()){
			if(!(it.next().necesita_orejas()))
				puede=true;
		}
		return puede;
	}
	
	// Added by jjpl @ for sonar review -> 30/1/2012
	
	public Integer getId_jugador_turno(){
		return this.id_jugador_turno;
	}

	
}
